home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Games / net3d-0.08 / object.c < prev    next >
C/C++ Source or Header  |  1995-06-22  |  30KB  |  1,222 lines

  1. /* object.c
  2.  *
  3.  * Functions for displaying and manipulting objects
  4.  */
  5. #include "net3d.h"
  6.  
  7. double gtm=0.0;                /* total time elapsed since */
  8.                     /* start of game */
  9.  
  10. int vidcount=0;                /* total number of vehicles */
  11.                     /* created so far */
  12.  
  13. double vmax[TYPECOUNT]={79,35,25,    /* maximum velocities for the */
  14.             1000,0,1000,    /* different vehicle types. */
  15.             150,0,200,    /* used if no maximum is given */
  16.             0,100,0,
  17.             200,0,0,};
  18.  
  19. /* The extra vehicles/objects list is used for storing objects
  20.  * created in-game, such as bullets, walls and new trees. It also
  21.  * stores vehicle definitions made in the vehicle files, for later
  22.  * instantiation.
  23.  */
  24. struct vehicle *evhead;            /* head of the extra vehicles list */    
  25. struct object *eohead;            /* head of the extra objects list */
  26.  
  27. vehicle_type playertype;        /* vehicle type of player when
  28.                      * they are wandering around on foot */
  29.  
  30. /* prints stats about the world */
  31. void worldinfo(struct vehicle *vhead, struct object *ohead)
  32. {
  33. int vc=0;                /* vehicles */
  34. int oc=0;                /* objects */
  35. int fc=0;                /* faces */
  36. int pc=0;                /* points */
  37.  
  38. for(vc=0; vhead; vhead=vhead->next,vc++)
  39.     ;
  40. for(oc=0; ohead; ohead=ohead->next,oc++) {
  41.     fc += ohead->fcount;
  42.     pc += ohead->pcount;
  43.     }
  44. printf("%d vehicles\n%d objects\n%d faces\n%d points\n",vc,oc,fc,pc);
  45. }
  46.     
  47. /* prints the vehicle list on screen (debugging purposes only) */
  48. void dumpvehicles(struct vehicle *vhead)
  49. {
  50. int vc=0;
  51.  
  52. for(;vhead;vhead=vhead->next) {
  53.     struct object *obj;
  54.     int oc;
  55.  
  56.     printf("\nvehicle %d\n",vc++);
  57.     printf("\tpartcount=%d\n",vhead->partcount);
  58.     printf("\tname=%s\n",vhead->name);
  59.     printf("\tcode=%s\n",vhead->code);
  60.     printf("\tangle=%f\n",vhead->angle);
  61.     printf("\tvelocity=%f\n",vhead->velocity);
  62.  
  63.     printf("\tb-box %f %f %f to %f %f %f\n",vhead->bmin.x,
  64.      vhead->bmin.y,vhead->bmin.z,vhead->bmax.x,vhead->bmax.y,
  65.      vhead->bmax.z);
  66.  
  67.     for(oc=0;oc < vhead->partcount;oc++) {
  68.         int i;
  69.  
  70.         obj=vhead->parts[oc];
  71.         printf("\n\t\tobject %d\n",oc);
  72.         printf("\t\tpcount=%d fcount=%d\n",obj->pcount,obj->fcount);
  73.         printf("\t\tpos=%f %f %f\n",obj->pos.x,obj->pos.y,
  74.          obj->pos.z);
  75.         printf("\t\tcent=%f %f %f\n",obj->cent.x,obj->cent.y,
  76.          obj->cent.z);
  77.         printf("\t\tdist=%f\n",obj->dist);
  78.  
  79.         printf("\t\tpoints : ");
  80.         for(i=0;i < obj->pcount;i++)
  81.             printf("%f %f %f   ",obj->points[i].x,
  82.              obj->points[i].y,obj->points[i].z);
  83.         printf("\n");
  84.  
  85.         printf("\t\tfaces : ");
  86.         for(i=0;i < obj->fcount;i++) {
  87.             struct polygon *pol;
  88.             int j;
  89.  
  90.             pol=obj->faces+i;
  91.             printf("\n\t\t\tface %d\n",i);
  92.             printf("\t\t\tpcount=%d\n",pol->pcount);
  93.             printf("\t\t\tcolour=%ld\n",pol->colour);
  94.             printf("\t\t\ttype=%d\n",pol->type);
  95.             printf("\t\t\tpoints : ");
  96.             for(j=0;j < pol->pcount;j++)
  97.                 printf("%d ",pol->vertices[j]);
  98.             printf("\n");
  99.             }
  100.         }
  101.     }
  102. }
  103.  
  104. /* movevehicle - moves all the parts of a vehicle the distance they
  105.  * should move in a given time
  106.  *
  107.  * v        - vehicle to move
  108.  * tm        - travel time
  109.  */
  110. void movevehicle(struct vehicle *v, double tm, struct map *mp)
  111. {
  112. int i;
  113. struct object **ob;
  114. float xd,yd;                /* direction of travel */
  115. float xv,yv,zv=0.0;            /* travel movement */
  116. double rotz=0.0;            /* rotation of vehicle */
  117. struct point vcen;
  118. int mx,my;                /* map position */
  119. float ht;                /* height at that position */
  120. bool changed=false;            /* has bounding box changed */
  121. float mxf, myf;
  122.  
  123. ob=v->parts;
  124. vcen=ob[0]->pos;
  125. /* find position on map, and height at that point
  126.  */
  127. xd=jcos(v->angle);    yd=jsin(v->angle);
  128. if (mp->size) {
  129.     mx = mxf = (vcen.x + (xd*20))/mp->size;
  130.     my = myf = (vcen.y + (yd*20))/mp->size;
  131.     if (mxf >= 0 && myf >= 0 && mx<mp->map_w && my<mp->map_h)
  132.         ht = mp->ht[mx][my];
  133.     else
  134.         ht = 0.0;
  135.     }
  136. else {
  137.     ht = 0.0;
  138.     }
  139.  
  140. /* move forward, and drop down towards ground */
  141. if ((v->velocity || v->climb || vcen.z!=ht) && v->type!=t_scenery) {
  142.     xv=xd*tm*v->velocity;
  143.     yv=yd*tm*v->velocity;
  144.     zv=tm*v->climb;    
  145.     if (mp->ground && !v->flying && vcen.z>0)
  146.         v->climb -= tm*GRAVITY;        /* fall to earth */
  147.     if (vcen.z < 0 && mp->ground) {        /* keep above ground level */
  148.         zv = -vcen.z;
  149.         }
  150.     else if (vcen.z > v->max.altitude) {    /* .. and below ceiling */
  151.         zv = v->max.altitude-vcen.z;
  152.         v->climb = 0.0;
  153.         }
  154.     shiftvehicle(v,xv,yv,zv);
  155.     /* if there is a maximum range, decrease and explode when
  156.      * range limit is reached.
  157.      */
  158.     if (v->range) {
  159.         v->range -= tm*(dabs(v->velocity) + dabs(v->climb));
  160.         if (v->range < 0)
  161.             v->hp = -1;
  162.         }
  163.     }
  164.  
  165. /* slow down turn rate.
  166.  * NOTE!! - this can probably be removed.
  167.  */
  168. if (v->owner == o_player || v->owner == o_network) {
  169.     if (v->angle_vel > 0) {
  170.         v->angle_vel -= tm*dtor(FRICTION);
  171.         if (v->angle_vel < 0)
  172.             v->angle_vel = 0;
  173.         }
  174.     else if (v->angle_vel < 0) {
  175.         v->angle_vel += tm*dtor(FRICTION);
  176.         if (v->angle_vel > 0)
  177.             v->angle_vel = 0;
  178.         }
  179.  
  180.     /* slow down turret turn rate */
  181.     for(i=0; i<v->partcount; i++) {
  182.         if (v->parts[i]->turret) {
  183.             if (v->parts[i]->angle_vel > 0) {
  184.                 v->parts[i]->angle_vel -= tm*dtor(FRICTION);
  185.                 if (v->parts[i]->angle_vel < 0)
  186.                     v->parts[i]->angle_vel = 0;
  187.                 }
  188.             else if (v->parts[i]->angle_vel < 0) {
  189.                 v->parts[i]->angle_vel += tm*dtor(FRICTION);
  190.                 if (v->parts[i]->angle_vel > 0)
  191.                     v->parts[i]->angle_vel = 0;
  192.                 }
  193.             }
  194.         }
  195.     }
  196.  
  197. /* rotate all parts of the vehicle.
  198.  * rotation is angle_vel radians per second.
  199.  */
  200. if (v->angle_vel != 0) {
  201.     changed=true;
  202.     rotz=tm*v->angle_vel;
  203.     v->angle += rotz;
  204.     if (v->angle < 0)            /* keep angle within */
  205.         v->angle += 2*PI;        /* 0 - 2PI */
  206.     else if (v->angle > 2*PI)
  207.         v->angle -= 2*PI;
  208.     for(i=0; i < v->partcount; i++)
  209.         rotatez(v->parts[i],rotz);
  210.     }
  211.  
  212.  
  213. /* rotate separate sections as well (ie gun turrets) */
  214. for(i=0; i<v->partcount; i++) {
  215.     v->parts[i]->angle += rotz;
  216.     if (v->parts[i]->angle_vel) {
  217.         double rotz2;            /* rotation for part */
  218.  
  219.         changed=true;
  220.         rotz2=tm*v->parts[i]->angle_vel;
  221.         rotatez(v->parts[i],rotz2);
  222.         v->parts[i]->angle += rotz2;
  223.         }
  224.     }
  225.  
  226. /* check for collision with ground hills, or with the ground if
  227.  * there is any.
  228.  */
  229. if (vcen.z < ht && (ht != 0.0 || mp->ground)) {
  230.     /* if a mountain has been hit, bounce back a bit */
  231.     if (v->type == t_bullet || v->type == t_shrapnel ||
  232.      v->type == t_seedpod) {
  233.         /* Some things are always destroyed on impact with
  234.          * the ground or a hill. */
  235.         v->hp = -1;
  236.         }
  237.     else {
  238.         if (ht) {
  239.             /* impact with a hill */
  240.             shiftvehicle(v,-xv*2,-yv*2,0);
  241.             v->hp -= (v->velocity < 5) ? 0 : 5;
  242.             }
  243.         else {
  244.             /* impact with the ground */
  245.             v->hp -= 5;
  246.             }
  247.         v->velocity = 0.0;
  248.         v->climb = 0.0;
  249.         v->angle_vel = 0.0;
  250.         v->bumped = True;
  251.         }
  252.     }
  253.  
  254. /* apply oscillation vectors */
  255. for(i=0; i<v->partcount; i++) {
  256.     int j;
  257.     struct object *ob;
  258.     ob=v->parts[i];
  259.     for(j=0; j<ob->ocount; j++) {
  260.         float osc;        /* amount oscillated (0-1) */
  261.         osc=ob->oscli[j].func(gtm*ob->oscli[j].rate + 
  262.          ob->oscli[j].phase);
  263.         if (ob->oscli[j].axes & OSC_X_AXIS)
  264.             ob->oscli[j].pt->x = ob->oscli[j].init.x +
  265.              ob->oscli[j].ovec.x*osc;
  266.         if (ob->oscli[j].axes & OSC_Y_AXIS)
  267.             ob->oscli[j].pt->y = ob->oscli[j].init.y +
  268.              ob->oscli[j].ovec.y*osc;
  269.         if (ob->oscli[j].axes & OSC_Z_AXIS)
  270.             ob->oscli[j].pt->z = ob->oscli[j].init.z +
  271.              ob->oscli[j].ovec.z*osc;
  272.         changed=true;
  273.         }
  274.     }
  275.  
  276. /* apply spin factors */
  277. if (v->xspin_vel) {
  278.     for(i=0; i < v->partcount; i++)
  279.         rotatex(v->parts[i],tm*v->xspin_vel);
  280.     changed=true;
  281.     }
  282. if (v->yspin_vel) {
  283.     for(i=0; i < v->partcount; i++)
  284.         rotatey(v->parts[i],tm*v->yspin_vel);
  285.     changed=true;
  286.     }
  287. if (v->zspin_vel) {
  288.     for(i=0; i < v->partcount; i++)
  289.         rotatez(v->parts[i],tm*v->zspin_vel);
  290.     changed=true;
  291.     }
  292.  
  293.  
  294.  
  295. /* slow down climb/dive, if appropriate.
  296.  */
  297. if (v->flying && v->type != t_bullet && v->type != t_shrapnel) {
  298.     if (v->climb > 0) {
  299.         v->climb -= tm*70;
  300.         if (v->climb < 0)
  301.             v->climb = 0;
  302.         }
  303.     if (v->climb < 0) {
  304.         v->climb += tm*70;
  305.         if (v->climb > 0)
  306.             v->climb = 0;
  307.         }
  308.     }
  309.  
  310. /* decrease reload time */
  311. if (v->reload > 0)
  312.     v->reload -= tm;
  313.  
  314. /* increase time since last hit */
  315. if (v->lasthit >= 0)
  316.     v->lasthit += tm;
  317.  
  318. /* decrease timer used in brain */
  319. if (v->ftimer >= 0)
  320.     v->ftimer -= tm;
  321.  
  322. /* re-calculate bounding box if object has been rotated, oscillated
  323.  * or spun, changing the points */
  324. if (changed)
  325.     calcbbox(v);
  326. }
  327.  
  328. void movevehicles(struct vehicle **vh, struct object **oh, struct map *mp,
  329.  double gtime)
  330. {
  331. static double ctime=0.0;        /* time at last call */
  332. double ntime;                /* time for this call */
  333. struct vehicle *v,*va,*vb;
  334. int tmp;
  335. double tm;
  336. struct vehicle *vnext;
  337.  
  338. /* find time since last movevehicles, from time passed in as parameter.
  339.  * This time comes from the server, making sure that all clients are
  340.  * synchronised.
  341.  */
  342. if (!ctime) {
  343.     ctime=gtime;
  344.     return;
  345.     }
  346. ntime=gtime;
  347. tm = ntime-ctime;            /* time to move for this call */
  348.  
  349. /* check for vehicle-vehicle collisions. */
  350. for(va=*vh; va; va=vnext) {
  351.     vnext = va->next;
  352.     if ((vb = collide(va,*vh))) {
  353.         /* check for transfer to another vehicle.  */
  354.         if (enteredvehicle(va,vb)) {
  355.             /* va has entered vb */
  356.             va->transfer = vb->vid;
  357.             vb->owner = o_network;
  358.             vb->res = va->res;
  359.             vb->pnum = va->pnum;
  360.             freevehicle(va,vh,oh);
  361.             continue;
  362.             }
  363.         if (enteredvehicle(vb,va)) {
  364.             /* vb has entered va */
  365.             vb->transfer = va->vid;
  366.             va->owner = o_network;
  367.             va->res = vb->res;
  368.             va->pnum = vb->pnum;
  369.             freevehicle(vb,vh,oh);
  370.             continue;
  371.             }
  372.  
  373.         /* check for resource collection */
  374.         if (va->type == playertype && vb->type == t_tree) {
  375.             va->res += 5;
  376.             freevehicle(vb,vh,oh);
  377.             continue;
  378.             }
  379.         if (vb->type == playertype && va->type == t_tree) {
  380.             vb->res += 5;
  381.             freevehicle(va,vh,oh);
  382.             continue;
  383.             }
  384.  
  385.         /* check for collecting a bonus item */
  386.         if (va->type == t_weapon && (vb->owner == o_player ||
  387.                          vb->owner == o_network)) {
  388.             vb->weapon = va->weapon;
  389.             freevehicle(va,vh,oh);
  390.             continue;
  391.             }
  392.         if (vb->type == t_weapon && (va->owner == o_player ||
  393.                          va->owner == o_network)) {
  394.             va->weapon = vb->weapon;
  395.             freevehicle(vb,vh,oh);
  396.             continue;
  397.             }
  398.  
  399.         /* check for collecting a munitions bonus */
  400.         if (va->type == t_munitions && (vb->owner == o_player ||
  401.                            vb->owner == o_network)) {
  402.             vb->ammo += va->ammo;
  403.             freevehicle(va,vh,oh);
  404.             continue;
  405.             }
  406.         if (vb->type == t_munitions && (va->owner == o_player ||
  407.                            va->owner == o_network)) {
  408.             va->ammo += va->ammo;
  409.             freevehicle(va,vh,oh);
  410.             continue;
  411.             }
  412.  
  413.         /* damage both */
  414.         tmp = va->hp;
  415.         va->hp -= vb->hp;
  416.         vb->hp -= tmp;
  417.  
  418.         /* record last hit time */
  419.         if (vb->type == t_bullet || vb->type == t_missile)
  420.             va->lasthit = 0.0;
  421.         else
  422.             va->bumped  = True;
  423.         if (va->type == t_bullet || va->type == t_missile)
  424.             vb->lasthit = 0.0;
  425.         else
  426.             vb->bumped  = True;
  427.  
  428.         /* halt both vehicles, except for those that have been
  429.          * hit by a bullet.
  430.          */
  431.         if (vb->type != t_bullet) {
  432.             va->velocity=0.0;
  433.             va->angle_vel=0.0;
  434.             }
  435.         if (va->type != t_bullet) {
  436.             vb->velocity=0.0;
  437.             vb->angle_vel=0.0;
  438.             }
  439.  
  440.         /* If a bullet hits something, make sure that it is
  441.          * destroyed.
  442.          */
  443.         if (va->type==t_bullet || va->type==t_missile ||
  444.          va->type == t_mine)
  445.             va->hp = -1;
  446.         if (vb->type==t_bullet || vb->type==t_missile ||
  447.          vb->type == t_mine)
  448.             vb->hp = -1;
  449.  
  450.         /* kludge - if two vehicles with equal hp collide, then make
  451.          * them both explode, otherwise they will both end up on
  452.          * hp 0, and have no further effect on each other.
  453.          */
  454.         if (!va->hp && !vb->hp) {
  455.             va->hp = vb->hp = -1;
  456.             }
  457.         /*
  458.         printf("%s has hit %s\n", va->code,vb->code);
  459.         */
  460.         }
  461.     }
  462.  
  463. /* apply move to all vehicles, except for static and scenery types */
  464. for(v=*vh; v; v = vnext) {
  465.     vnext = v->next;
  466.     if (v->type != t_scenery && v->type != t_static && v->type != t_mine)
  467.         movevehicle(v,tm,mp);
  468.     if (v->hp < 0) {
  469.         if (v->type == t_tree) {
  470.             /* If a tree is hit by something, then change it's
  471.              * type to static, so that it doesn't explode into
  472.              * seedpods.
  473.              */
  474.             v->type = t_static;
  475.             }
  476.         explode(vh,oh,v);
  477.         }
  478.     }
  479.  
  480. /* increment game time, and store current time for this call */
  481. gtm += ntime-ctime;
  482. ctime=ntime;
  483. }
  484.  
  485. void multpoints(struct object *ob, float mat[3][3])
  486. {
  487. struct point src;
  488. int i;
  489.  
  490. /* multiply points */
  491. for(i=0; i < ob->pcount; i++) {
  492.     src=ob->points[i];
  493.     mmult(&src,mat,ob->points+i);
  494.     }
  495.  
  496. /* multiply centre */
  497. src=ob->cent;
  498. mmult(&src,mat,&ob->cent);
  499.  
  500. /* multiply oscillation vectors, except for those applying to the
  501.  * position of an object instead of one of it's points.
  502.  */
  503. for(i=0; i<ob->ocount; i++) {
  504.     if (ob->oscli[i].pt != &ob->pos) {
  505.         src=ob->oscli[i].init;
  506.         mmult(&src,mat,&(ob->oscli[i].init));
  507.         }
  508.     src=ob->oscli[i].ovec;
  509.     mmult(&src,mat,&(ob->oscli[i].ovec));
  510.     }
  511. }
  512.  
  513. void rotatez(struct object *ob, double rad)
  514. {
  515. float rotm[3][3]={{1,0,0},{0,1,0},{0,0,1}};
  516.  
  517. rotm[0][0]=(float)jcos(rad); rotm[1][0]=(float)jsin(rad);
  518. rotm[0][1]=-rotm[1][0];     rotm[1][1]=rotm[0][0];
  519. multpoints(ob,rotm);
  520. }
  521.  
  522. void rotatex(struct object *ob, double rad)
  523. {
  524. float rotm[3][3]={{1,0,0},{0,1,0},{0,0,1}};
  525.  
  526. rotm[1][1]=(float)jcos(rad); rotm[2][1]=(float)jsin(rad);
  527. rotm[1][2]=-rotm[2][1];     rotm[2][2]=rotm[1][1];
  528. multpoints(ob,rotm);
  529. }
  530.  
  531. void rotatey(struct object *ob, double rad)
  532. {
  533. float rotm[3][3]={{1,0,0},{0,1,0},{0,0,1}};
  534.  
  535. rotm[0][0]=(float)jcos(rad); rotm[2][0]=(float)-jsin(rad);
  536. rotm[0][2]=-rotm[2][0];     rotm[2][2]=rotm[0][0];
  537. multpoints(ob,rotm);
  538. }
  539.  
  540. double gametime(void)
  541. {
  542. struct timeval tv;
  543. struct timezone tz;
  544. gettimeofday(&tv,&tz);
  545. return tv.tv_sec+tv.tv_usec/1000000.0;
  546. }
  547.  
  548.  
  549. void makemap(struct object **ohead, struct map *mp)
  550. {
  551. int i,j;
  552.  
  553. /* generate ground objects (map starts at 0,0).
  554.  */
  555. for(i=0; i<mp->map_w; i++)
  556.     for(j=0; j<mp->map_h; j++) {
  557.         float c0,c1,c2,c3;        /* corner heights */
  558.         struct point ps,ct;
  559.         struct point pts[4];
  560.         int facepts[4]={0,1,3,2};
  561.         struct polygon fcs[1]={{4,NULL,0,f_plane}};
  562.  
  563.         /* heights at each polygon corner are the average of */
  564.         /* the heights of surrounding polygons */
  565.         c0=calcmap(i,j,mp);
  566.         c1=calcmap(i,j+1,mp);
  567.         c2=calcmap(i+1,j+1,mp);
  568.         c3=calcmap(i+1,j,mp);
  569.         mp->ht[i][j]=(c0+c1+c2+c3)/4.0;    /* average polygon height */
  570.         if (mp->ht[i][j] == 0)
  571.             /* zero height */
  572.             continue;
  573.  
  574.         /* each ground square is a single rectangle */
  575.         /* position */
  576.         ps.x=i*mp->size;
  577.         ps.y=j*mp->size;
  578.         ps.z=0.0;
  579.         /* centre */
  580.         ct.x=mp->size/2;
  581.         ct.y=mp->size/2;
  582.         ct.z=0.0;
  583.         /* points */
  584.         pts[0].x=0;        pts[0].y=0;        pts[0].z=c0;
  585.         pts[1].x=mp->size;    pts[1].y=0;        pts[1].z=c3;
  586.         pts[2].x=0;        pts[2].y=mp->size;    pts[2].z=c1;
  587.         pts[3].x=mp->size;    pts[3].y=mp->size;    pts[3].z=c2;
  588.         /* faces */
  589.         fcs[0].vertices=facepts;
  590.         fcs[0].colour=(mp->tcol*32)+31-(mp->gr[i][j]/mp->scale)*31;
  591.         addobject(ohead,ps,ct,NULL,4,1,pts,fcs);
  592.         (*ohead)->mx = i;
  593.         (*ohead)->my = j;
  594.         }
  595. }
  596.  
  597. struct object *addobject(struct object **ohead, struct point pos, struct
  598.  point cent, struct vehicle *par, int pc, int fc, struct point *pts, struct
  599.  polygon *fcs)
  600. {
  601. struct object *no;
  602. int i;
  603.  
  604. /* make a new object, containing deep copies of all the points/faces
  605.  * passed in as parameters */
  606. no=(struct object *)calloc(1,sizeof(struct object));
  607. no->next=(*ohead);
  608. (*ohead)=no;
  609. no->pcount=pc;
  610. no->fcount=fc;
  611. no->points=(struct point *)calloc(pc,sizeof(struct point));
  612. no->cpoints=(struct point *)calloc(pc,sizeof(struct point));
  613. no->ppoints=(XPoint *)calloc(pc,sizeof(XPoint));
  614. memcpy(no->points,pts,pc*sizeof(struct point));
  615. no->faces=(struct polygon *)calloc(fc,sizeof(struct polygon));
  616. for(i=0; i<fc; i++) {
  617.     no->faces[i].pcount=fcs[i].pcount;
  618.     no->faces[i].colour=fcs[i].colour;
  619.     no->faces[i].type=fcs[i].type;
  620.     no->faces[i].vertices=calloc(fcs[i].pcount,sizeof(int));
  621.     memcpy(no->faces[i].vertices,fcs[i].vertices,fcs[i].pcount*
  622.      sizeof(int));
  623.     }
  624. no->pos=pos;
  625. no->cent=cent;
  626. no->dist=0.0;
  627. no->parent=par;
  628. no->clockwise=true;
  629. no->cvalid = false;
  630. no->mightsave = false;
  631. return no;
  632. }
  633.  
  634. /* calculates the height of the bottom-left corner of map square x,y */
  635. float calcmap(int x, int y, struct map *m)
  636. {
  637. float sum=0.0;
  638. sum += (x < m->map_w && y < m->map_h     ? m->gr[x][y] : 0.0);
  639. sum += (x > 0 && y < m->map_h         ? m->gr[x-1][y] : 0.0);
  640. sum += (x > 0 && y > 0             ? m->gr[x-1][y-1] : 0.0);
  641. sum += (x < m->map_w && y > 0         ? m->gr[x][y-1] : 0.0);
  642. return sum/4.0;
  643. }
  644.  
  645.  
  646. /* explode - removes a vehicle from the game, possibly with a large
  647.  * explosion of shrapnel and several flaming fireballs.
  648.  *
  649.  * vhead    - pointer to the head of the vehicle list
  650.  * ohead    - pointer to the head of the object list
  651.  * t        - the vehicle to explode
  652.  */
  653. void explode(struct vehicle **vhead, struct object **ohead, struct
  654.  vehicle *t)
  655. {
  656. int i,j;
  657. struct point vcen;
  658.  
  659. /*
  660. printf("exploding %s\n",t->code);
  661. */
  662. vcen=t->parts[0]->pos;            /* get position of vehicle */
  663.  
  664. if (t->type != t_shrapnel && t->type != t_seedpod) {
  665.     /* create blast fragments */
  666.     for(i=0; i<t->partcount; i++) {
  667.         int j;
  668.         struct object *ob;
  669.  
  670.         ob=t->parts[i];
  671.         for(j=0; j<ob->fcount; j++) {
  672.             struct vehicle *nv;
  673.             struct point pts[MAX_POINTS_PER_OBJECT];
  674.             struct polygon fcs[1];
  675.             int facepts[MAX_POINTS_PER_FACE];
  676.             int pc,k;
  677.             struct point pos;
  678.             struct point cent={0,0,0};
  679.  
  680.             /* create a new vehicle structure */
  681.             nv=(struct vehicle *)calloc(1,sizeof(struct vehicle));
  682.             nv->next=(*vhead);        /* add to list */
  683.             *vhead=nv;
  684.             nv->partcount        = 1;
  685.             nv->owner        = o_game;
  686.             if (t->type == t_tree && rand()%SEEDCHANCE == 0)
  687.                 nv->type = t_seedpod;
  688.             else
  689.                 nv->type = t_shrapnel;
  690.             nv->weapon        = w_none;
  691.             nv->flying        = false;
  692.             nv->code        = strdupe("shrapnel");
  693.             nv->name        = strdupe("a blast fragment");
  694.             nv->velocity        = rand()%40;
  695.             nv->climb        = (rand()%60)-20;
  696.             nv->angle        = dtor(rand()%360);
  697.             nv->hp            = 1;
  698.             nv->alive        = true;
  699.             nv->vid            = vidcount++;
  700.             nv->parts        = (struct object **)
  701.                           calloc(1,sizeof(
  702.                           struct object *));
  703.             nv->max.velocity    = MAX_VELOCITY;
  704.             nv->max.angle_vel    = MAX_ANGLE_VEL;
  705.             nv->max.altitude    = MAX_ALTITUDE;
  706.             nv->transfer        = -1;
  707.             nv->buildervid        = -1;
  708.             nv->seed        = strdupe(t->seed);
  709.             nv->pnum         = -1;
  710.             nv->range        = 200;
  711.             nv->stcount        = 0;
  712.             nv->states        = NULL;
  713.             nv->currentstate    = -1;
  714.             nv->lasthit        = 0.0;
  715.  
  716.             /* extract the points from the original object
  717.              * which are used in the fragment.
  718.              */
  719.             for(pc=0; pc<ob->faces[j].pcount; pc++) {
  720.                 facepts[pc] = pc;
  721.                 pts[pc] = ob->points[ob->faces[j].
  722.                  vertices[pc]];
  723.                 }
  724.             fcs[0].pcount=pc;
  725.             fcs[0].vertices=facepts;
  726.             fcs[0].colour=ob->faces[j].colour;
  727.             fcs[0].type=ob->faces[j].type;
  728.  
  729.             /* change points in new object so that the
  730.              * minimum point is at 0,0,0
  731.              */
  732.             pos=pts[0];
  733.             for(k=0; k<pc; k++) {
  734.                 if (pos.x < pts[k].x)
  735.                     pos.x=pts[k].x;
  736.                 if (pos.y < pts[k].y)
  737.                     pos.y=pts[k].y;
  738.                 if (pos.z < pts[k].z)
  739.                     pos.z=pts[k].z;
  740.                 }
  741.             for(k=0; k<pc; k++) {
  742.                 pts[k].x -= pos.x;
  743.                 pts[k].y -= pos.y;
  744.                 pts[k].z -= pos.z;
  745.                 }
  746.             /* add the initial position of the victim to
  747.              * the position of the fragment.
  748.              */
  749.             pos.x += ob->pos.x;
  750.             pos.y += ob->pos.y;
  751.             pos.z += ob->pos.z + 5;
  752.  
  753.             /* give the fragment a random spin factor */
  754.             nv->xspin_vel = dtor(rand()%20);
  755.             nv->yspin_vel = dtor(rand()%20);
  756.             nv->zspin_vel = dtor(rand()%20);
  757.  
  758.             /* create fragment object, which is one part of */
  759.             /* the original object */
  760.             nv->parts[0]=addobject(ohead,pos,cent,nv,pc,1,pts,fcs);
  761.             }
  762.         }
  763.     }
  764.  
  765. /* create several flaming fireballs when a vehicle explodes.
  766.  */
  767. if (t->type == t_tank || t->type == t_hover || t->type == t_fixedwing ||
  768.  t->type == t_gunsite || t->type == t_mine) {
  769.     for(i=0; i<FIREBALLS; i++) {
  770.         struct vehicle *nv;
  771.         char firename[15];
  772.  
  773.         /* create the new fireball vehicle structure.
  774.          */
  775.         nv = (struct vehicle *)calloc(1,sizeof(struct vehicle));
  776.         nv->parts = (struct object **)calloc(MAX_PARTS_PER_VEHICLE,
  777.                    sizeof(struct object *));    
  778.         nv->next = *vhead;
  779.         *vhead = nv;
  780.  
  781.         /* copy a fireball from the extra vehicles list.
  782.          */
  783.         sprintf(firename,"fireball%d",rand()%7 + 25);
  784.         copyvehicle(nv,findbycode(evhead,firename),ohead);
  785.  
  786.         /* set attributes */
  787.         nv->code     = strdupe("fireball");
  788.         nv->velocity = rand()%35;
  789.         nv->climb    = (rand()%60)-20;
  790.         nv->angle    = dtor(rand()%360);
  791.         nv->firer    = NULL;
  792.         nv->vid      = vidcount++;
  793.         nv->alive    = true;
  794.         nv->range    = 200;
  795.  
  796.         /* position it near the dead vehicle */
  797.         for(j=0; j<nv->partcount; j++) {
  798.             addpts(nv->parts[j]->pos,t->parts[0]->pos,
  799.                    &nv->parts[j]->pos);
  800.             nv->parts[j]->pos.z += 5;
  801.             }
  802.         calcbbox(nv);
  803.         }
  804.     }
  805.  
  806. /* create new trees when a seedpod hits the ground.
  807.  */
  808. if (t->type == t_seedpod) {
  809.     /* This is a seedpod. Create a tree at this spot. 
  810.      */
  811.     struct vehicle *nv;
  812.     int i;
  813.     struct point pos;
  814.     struct vehicle *seedv;
  815.  
  816.     nv = (struct vehicle *)calloc(1,sizeof(struct vehicle));
  817.     nv->parts = (struct object **)calloc(MAX_PARTS_PER_VEHICLE,
  818.                          sizeof(struct object *));
  819.     nv->next = *vhead;
  820.     *vhead = nv;
  821.  
  822.     /* Copy the tree object */
  823.     seedv = findbycode(evhead,t->seed);
  824.     copyvehicle(nv,seedv,ohead);
  825.     nv->code=strdupe(seedv->code);
  826.  
  827.     /* position it at the impact point of the seedpod */
  828.     pos = t->parts[0]->pos;
  829.     for(i=0; i<nv->partcount; i++) {
  830.         nv->parts[i]->pos.x += pos.x;
  831.         nv->parts[i]->pos.y += pos.y;
  832.         if (pos.z > 0)
  833.             nv->parts[i]->pos.z += pos.z;
  834.         }
  835.  
  836.     /* set new tree's attributes */
  837.     nv->alive = true;
  838.     nv->vid = vidcount++;
  839.     calcbbox(nv);
  840.     }
  841.  
  842. freevehicle(t,vhead,ohead);
  843. }
  844.  
  845. void freevehicle(struct vehicle *t, struct vehicle **vhead, struct
  846.  object **ohead)
  847. {
  848. int i,j;
  849. struct object **opos;
  850. struct vehicle **vpos;
  851.  
  852. for(vpos=vhead; *vpos != t; vpos=&((*vpos)->next))
  853.     ;                /* find pointer to to victim on list */
  854. *vpos=t->next;                /* route list around it */
  855.  
  856. /* free up all vehicle's objects */
  857. for(i=0; i<t->partcount; i++) {
  858.     for(opos=ohead; *opos != t->parts[i]; opos=&((*opos)->next))
  859.         ;            /* find pointer to object on list */
  860.     *opos=t->parts[i]->next;    /* re-route list */
  861.     /* free all the point lists of the polygons of the object */
  862.     for(j=0; j<t->parts[i]->fcount; j++) {
  863.         free(t->parts[i]->faces[j].vertices);
  864.         }
  865.     /* free the polygons of the object */
  866.     free(t->parts[i]->faces);
  867.     /* free oscillators */
  868.     free(t->parts[i]->oscli);
  869.     /* free points */
  870.     free(t->parts[i]->points);
  871.     free(t->parts[i]->cpoints);
  872.     free(t->parts[i]->ppoints);
  873.     free(t->parts[i]);        /* free object */
  874.     }
  875.  
  876. /* free up the vehicle's brain */
  877. for(i=0; i<t->stcount; i++) {
  878.     free(t->states[i].links);
  879.     }
  880. if (t->states)
  881.     free(t->states);
  882.  
  883. /* totally free vehicle */
  884. free(t->name);
  885. free(t->parts);
  886. free(t->code);
  887. if (t->seed)
  888.     free(t->seed);
  889.  
  890. if (t->owner != o_player) {
  891.     free(t);
  892.     }
  893. else
  894.     t->alive=false;
  895. }
  896.  
  897. /* calculate the bounding box for a single vehicle, by finding the
  898.  * minimum and maximum x,y and z values for that vehicle's points
  899.  */
  900. void calcbbox(struct vehicle *v)
  901. {
  902. int i,j;
  903. struct object *ob;
  904. struct point pt;
  905.  
  906. /* initial min&max from first point in first object */
  907. ob=v->parts[0];
  908. v->bmax.x = v->bmin.x = ob->points[0].x + ob->pos.x;
  909. v->bmax.y = v->bmin.y = ob->points[0].y + ob->pos.y;
  910. v->bmax.z = v->bmin.z = ob->points[0].z + ob->pos.z;
  911.  
  912. /* loop through all points, and find min&max x,y & z values */
  913. for(i=0; i<v->partcount; i++) {
  914.     ob=v->parts[i];
  915.     for(j=0; j<ob->pcount; j++) {
  916.         pt.x = ob->points[j].x + ob->pos.x;
  917.         pt.y = ob->points[j].y + ob->pos.y;
  918.         pt.z = ob->points[j].z + ob->pos.z;
  919.         /* find min & max x */
  920.         if (pt.x < v->bmin.x)
  921.             v->bmin.x=pt.x;
  922.         else if (pt.x > v->bmax.x)
  923.             v->bmax.x=pt.x;
  924.         /* ditto for y */
  925.         if (pt.y < v->bmin.y)
  926.             v->bmin.y=pt.y;
  927.         else if (pt.y > v->bmax.y)
  928.             v->bmax.y=pt.y;
  929.         /* and for z */
  930.         if (pt.z < v->bmin.z)
  931.             v->bmin.z=pt.z;
  932.         else if (pt.z > v->bmax.z)
  933.             v->bmax.z=pt.z;
  934.         }
  935.     }
  936. }
  937.  
  938. /* calculate bounding boxes for the whole vehicle list */
  939. void calcbboxes(struct vehicle *vhead)
  940. {
  941. for(; vhead; vhead=vhead->next)
  942.     calcbbox(vhead);
  943. }
  944.  
  945. void shiftvehicle(struct vehicle *v, float x, float y, float z)
  946. {
  947. int i;
  948.  
  949. #if 1
  950. for(i=0; i<v->partcount; i++) {
  951.     /* shift object positions */
  952.     v->parts[i]->pos.x += x;
  953.     v->parts[i]->pos.y += y;
  954.     v->parts[i]->pos.z += z;
  955.     }
  956. #endif
  957. /* shift bounding box */
  958. v->bmin.x += x;
  959. v->bmin.y += y;
  960. v->bmin.z += z;
  961. v->bmax.x += x;
  962. v->bmax.y += y;
  963. v->bmax.z += z;
  964. }
  965.  
  966. void fire(struct vehicle **vhead, struct object **ohead, struct vehicle *f)
  967. {
  968. struct vehicle *nv;
  969. struct point pos;
  970. struct object *tur;
  971. int i;
  972.  
  973. if (f->weapon==w_none || f->reload > 0 || !f->ammo)
  974.     return;
  975.  
  976. f->ammo--;            /* decrease ammunition */
  977.  
  978. /* create a new vehicle structure, and add it to the list.
  979.  */
  980. nv = (struct vehicle *)calloc(1,sizeof(struct vehicle));
  981. nv->parts = (struct object **)calloc(MAX_PARTS_PER_VEHICLE,
  982.                      sizeof(struct object *));
  983. nv->next = *vhead;
  984. *vhead = nv;
  985. nv->range=2000.0;
  986.  
  987. switch(f->weapon) {
  988. case w_tracer:
  989.     copyvehicle(nv,findbycode(evhead,"tracer"),ohead);
  990.     nv->code=strdupe("tracer");
  991.     nv->velocity = max(f->velocity,0)+200;
  992.     f->reload = 0.3;
  993.     break;
  994. case w_shell:
  995.     copyvehicle(nv,findbycode(evhead,"shell"),ohead);
  996.     nv->code = strdupe("shell");
  997.     nv->velocity = max(f->velocity,0)+100;
  998.     f->reload = 1.0;
  999.     break;
  1000. case w_bomb:
  1001.     copyvehicle(nv,findbycode(evhead,"bomb"),ohead);
  1002.     nv->code = strdupe("bomb");
  1003.     nv->velocity = f->velocity;
  1004.     f->reload = 1.0;
  1005.     break;
  1006. case w_bullet:
  1007.     copyvehicle(nv,findbycode(evhead,"bullet"),ohead);
  1008.     nv->code = strdupe("bullet");
  1009.     nv->velocity = max(f->velocity,0)+150;
  1010.     f->reload = 0.2;
  1011.     break;
  1012. case w_flame:
  1013.     copyvehicle(nv,findbycode(evhead,"flame"),ohead);
  1014.     nv->code = strdupe("flame");
  1015.     nv->velocity = max(f->velocity,0)+100;
  1016.     nv->range = 500;
  1017.     f->reload = 2.5;
  1018.     break;
  1019. case w_missile:
  1020.     copyvehicle(nv,findbycode(evhead,"missile"),ohead);
  1021.     nv->code = strdupe("missile");
  1022.     nv->velocity = max(f->velocity,0)+100;
  1023.     f->reload = 3.3;
  1024.     /* follow vehicle locked onto by firer */
  1025.     if (f->lock == -1)
  1026.         nv->target = -2;
  1027.     else
  1028.         nv->target = f->lock;
  1029.     break;
  1030. case w_chicken:
  1031.     copyvehicle(nv,findbycode(evhead,"chicken"),ohead);
  1032.     nv->code = strdupe("chicken");
  1033.     nv->velocity = max(f->velocity,0)+150;
  1034.     f->reload = 3.0;
  1035.     break;
  1036. case w_plasmaballs:
  1037.     copyvehicle(nv,findbycode(evhead,"plasmaballs"),ohead);
  1038.     nv->code = strdupe("plasmaballs");
  1039.     nv->velocity = max(f->velocity,0)+200;
  1040.     f->reload = 1.0;
  1041.     break;
  1042. case w_torpedo:
  1043.     copyvehicle(nv,findbycode(evhead,"torpedo"),ohead);
  1044.     nv->code = strdupe("torpedo");
  1045.     nv->velocity = max(f->velocity,0)+100;
  1046.     f->reload = 4.0;
  1047.     /* follow vehicle locked onto by firer */
  1048.     if (f->lock == -1)
  1049.         nv->target = -2;
  1050.     else
  1051.         nv->target = f->lock;
  1052.     break;
  1053. case w_none:
  1054.     /* no weapon */
  1055.     break;
  1056.     }
  1057.  
  1058. /* set attributes of new projectile */
  1059. nv->owner=o_game;
  1060. nv->weapon=w_none;
  1061. nv->firer=f;
  1062. nv->alive=true;
  1063. nv->vid=vidcount++;
  1064.  
  1065. /* store missile's vid in firer */
  1066. f->missile = nv->vid;
  1067.  
  1068. /* find firing angle and fire position */
  1069. tur = findturret(f);
  1070. if (tur) {
  1071.     nv->angle = tur->angle;
  1072.     addpts(tur->pos,tur->cent,&pos);
  1073.     }
  1074. else {
  1075.     nv->angle=f->angle;
  1076.     addpts(f->parts[0]->pos, f->parts[0]->cent,&pos);
  1077.     }
  1078.  
  1079. /* add the firing position to all objects in the projectile vehicle */
  1080. for(i=0; i<nv->partcount; i++) {
  1081.     nv->parts[i]->pos.x += pos.x;
  1082.     nv->parts[i]->pos.y += pos.y;
  1083.     nv->parts[i]->pos.z += pos.z;
  1084.     }
  1085.  
  1086. /* add climb to projectile, so that it rises at the correct rate. */
  1087. nv->climb = tan(f->turret_ang)*nv->velocity;
  1088.  
  1089. /* rotate projectile to correct angle */
  1090. for(i=0; i<nv->partcount; i++) {
  1091.     rotatey(nv->parts[i],-(f->turret_ang));
  1092.     rotatez(nv->parts[i],nv->angle);
  1093.     }
  1094. calcbbox(nv);
  1095. }
  1096.  
  1097. double dabs(double x)
  1098. {
  1099. return (x > 0 ? x : -x);
  1100. }
  1101.  
  1102. /* returns the square of the sin of it's argument */
  1103. double sinsq(double x)
  1104. {
  1105. double s;
  1106. s=jsin(x);
  1107. return s*s;
  1108. }
  1109.  
  1110. /* returns the sin of it's argument, scaled from 0 to 1 */
  1111. double sinhalf(double x)
  1112. {
  1113. return (jsin(x)+1.0)/2.0;
  1114. }
  1115.  
  1116. /* Read the array of strings in extras.c, and send them through a pipe to
  1117.  * readfiles().
  1118.  */
  1119. void readextravehicles(void)
  1120. {
  1121. int fds[2];
  1122.  
  1123. pipe(fds);
  1124. if (!fork()) {
  1125.     /* Read extra vehicles, and write them to the pipe.
  1126.      */
  1127.     int i=0;
  1128.     while(extras[i])
  1129.         nprintf(fds[1],"%s\n",extras[i++]);
  1130.     nprintf(fds[1],"end\n");
  1131.     exit(0);
  1132.     }
  1133. else {
  1134.     readfile(&eohead,&evhead,fds[0],NULL);
  1135.     }
  1136. printf("done reading extra vehicles\n");
  1137. }
  1138.  
  1139. /* Ejects the player from his/her current vehicle. */
  1140. void eject(struct vehicle **vhead, struct object **ohead, struct vehicle *v)
  1141. {
  1142. struct vehicle *nv;
  1143. struct point pos;
  1144. int i;
  1145.  
  1146. /* create a new vehicle structure */
  1147. nv = (struct vehicle *)calloc(1,sizeof(struct vehicle));
  1148. nv->parts = (struct object **)calloc(MAX_PARTS_PER_VEHICLE,
  1149.                      sizeof(struct object *));
  1150. nv->next = *vhead;
  1151. *vhead = nv;
  1152.  
  1153. /* fill it in with a copy of the lifeform vehicle from the bullets file */
  1154. copyvehicle(nv,findbycode(evhead,"player"),ohead);
  1155. nv->code = strdupe("player");
  1156. nv->velocity = 0;
  1157. nv->owner = v->owner;
  1158. nv->climb = 0;
  1159. nv->alive = true;
  1160. nv->vid = vidcount++;
  1161. nv->target = -1;
  1162. nv->reload = 0;
  1163. nv->lock = -1;
  1164. nv->res = v->res;
  1165. nv->pnum = v->pnum;
  1166.  
  1167. /* position the player near their old vehicle */
  1168. pos = v->bmax;
  1169. for(i=0; i<nv->partcount; i++) {
  1170.     nv->parts[i]->pos.x += pos.x+6;
  1171.     nv->parts[i]->pos.y += pos.y+6;
  1172.     nv->parts[i]->pos.z += (v->bmin.z > 0 ? v->bmin.z : 0);
  1173.     }
  1174. calcbbox(nv);
  1175. }
  1176.  
  1177. /* returns true if a player f can enter the vehicle v.
  1178.  */
  1179. bool enteredvehicle(struct vehicle *f, struct vehicle *v)
  1180. {
  1181. if ((f->owner == o_player || f->owner == o_network) &&
  1182.     v->owner == o_none && f->type == findbycode(evhead,"player")->type)
  1183.     return true;
  1184. else
  1185.     return false;
  1186. }
  1187.  
  1188. /* rotatevehicle - rotate the given vehicle, and all it's parts.
  1189.  */
  1190. void rotatevehicle(struct vehicle *v, double newang)
  1191. {
  1192. int i;
  1193.  
  1194. for(i=0; i < v->partcount; i++)
  1195.     rotatez(v->parts[i],newang - v->angle);
  1196. for(i=0; i<v->partcount; i++)
  1197.     if (v->parts[i]->turret)
  1198.         v->parts[i]->angle += (newang - v->angle);
  1199. v->angle = newang;
  1200. }
  1201.  
  1202. /* calculates the square of the distance from vehicle v1 to v2. */
  1203. float vehicledist(struct vehicle *v1, struct vehicle *v2)
  1204. {
  1205. float xd,yd,zd;
  1206. struct point vp1,vp2;
  1207.  
  1208. vp1 = v1->parts[0]->pos;
  1209. vp2 = v2->parts[0]->pos;
  1210. xd = vp1.x - vp2.x;
  1211. yd = vp1.y - vp2.y;
  1212. zd = vp1.z - vp2.z;
  1213. return xd*xd + yd*yd + zd*zd;
  1214. }
  1215.  
  1216. /* calculates the altitude difference from v2 to v1 */
  1217. double heightdiff(struct vehicle *v1, struct vehicle *v2)
  1218. {
  1219. return v1->parts[0]->pos.z - v2->parts[0]->pos.z;
  1220. }
  1221.  
  1222.